﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace RegexCalc
{
    public partial class Form1 : Form
    {
        RgxClass rgx = new RgxClass();

        public Form1()
        {
            InitializeComponent();
            BindData();
            txtReplace_TextChanged(null, null);
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        void BindData()
        {
            this.txtInput.DataBindings.Clear();
            this.txtInput.DataBindings.Add("Text", rgx, "Source");
            this.txtPattern.DataBindings.Clear();
            this.txtPattern.DataBindings.Add("Text", rgx, "Pattern");
            this.txtReplace.DataBindings.Clear();
            this.txtReplace.DataBindings.Add("Text", rgx, "Replace");
            this.chkIgnoreCase.DataBindings.Clear();
            this.chkIgnoreCase.DataBindings.Add("Checked", rgx, "IgnoreCase");
            this.chkMultiLine.DataBindings.Clear();
            this.chkMultiLine.DataBindings.Add("Checked", rgx, "MultiLine");
        }

        private void btnCalc_Click(object sender, EventArgs e)
        {
            txtOutput.Text = "";
            RegexOptions ro = RegexOptions.None;
            if (chkIgnoreCase.Checked) ro |= RegexOptions.IgnoreCase;
            if (chkMultiLine.Checked) ro |= RegexOptions.Multiline;
            else ro |= RegexOptions.Singleline;

            string pattern = txtPattern.Text.Replace("\r", "\\r").Replace("\n", "\\n");
            if (String.IsNullOrEmpty(txtReplace.Text))
            {
                MatchCollection matches = null;
                try
                {
                    matches = Regex.Matches(txtInput.Text, pattern, ro);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }
                StringBuilder matchOut = new StringBuilder(1000);
                for (int k = 0; k < matches.Count; k++)
                {
                    // if (m.Index == 0) continue;
                    var m = matches[k];
                    matchOut.AppendFormat("Match[{0}]: Index={1} Length={2} Value={3}\r\n", k, m.Index, m.Length, TrimLong(m.Value));
                    if (m.Groups.Count > 1)
                    {
                        for (int i = 1; i < m.Groups.Count; i++)
                        {
                            var g = m.Groups[i];
                            matchOut.AppendFormat("  Group[{0}]: Index={1} Length={2} Value={3}\r\n", i, g.Index, g.Length, TrimLong(g.Value));
                            if (g.Captures.Count > 1)
                            {
                                for (int j = 0; j < g.Captures.Count; j++)
                                {
                                    var c = g.Captures[j];
                                    matchOut.AppendFormat("    Capture[{0}]: Index={1} Length={2} Value={3}\r\n", j, c.Index, c.Length, TrimLong(c.Value));
                                }
                            }
                        }
                    }
                }
                txtOutput.Text = matchOut.ToString();
                if (txtOutput.Text == "") txtOutput.Text = "没有找到匹配!";
            }
            else
            {
                try
                {
                    txtOutput.Text = Regex.Replace(txtInput.Text, pattern, txtReplace.Text, ro);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        string TrimLong(string str)
        {
            string value = str.Replace("\r", "\\r").Replace("\n", "\\n");
            if (value.Length > 50) value = value.Substring(0, 25) + "------" + value.Substring(value.Length - 25);
            return value;
        }

        private void txtReplace_TextChanged(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(rgx.Replace))
            {
                lblMethod.Text = "调用方法: Regex.Replace(input, pattern, replace, options)";
            }
            else
            {
                lblMethod.Text = "调用方法:Regex.Matches(input, pattern, options)";
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                XmlSerializer xs = new XmlSerializer(typeof(RgxClass));
                FileStream fs = new FileStream(saveFileDialog1.FileName, FileMode.Create);
                xs.Serialize(fs, rgx);
                fs.Close();
            }
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                XmlSerializer xs = new XmlSerializer(typeof(RgxClass));
                //http://bbs.csdn.net/topics/80179639 解决换行丢失问题
                XmlTextReader xr = new XmlTextReader(new FileStream(openFileDialog1.FileName, FileMode.Open));
                xr.Normalization = false;

                rgx = (RgxClass)xs.Deserialize(xr);
                xr.Close();
                BindData();
            }
        }

        public class RgxClass : INotifyPropertyChanged
        {
            private string _pattern;
            public string Pattern
            {
                get { return _pattern; }
                set
                {
                    if (_pattern != value)
                    {
                        _pattern = value;
                        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Pattern"));
                    }
                }
            }

            string _replace;
            public string Replace
            {
                get { return _replace; }
                set
                {
                    if (_replace != value)
                    {
                        _replace = value;
                        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Replace"));
                    }
                }
            }

            string _source;
            public string Source
            {
                get { return _source; }
                set
                {
                    if (_source != value)
                    {
                        _source = value;
                        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Source"));
                    }
                }
            }

            bool _ignoreCase;
            public bool IgnoreCase
            {
                get { return _ignoreCase; }
                set
                {
                    if (_ignoreCase != value)
                    {
                        _ignoreCase = value;
                        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IgnoreCase"));
                    }
                }
            }

            bool _multiLine;
            public bool MultiLine
            {
                get { return _multiLine; }
                set
                {
                    if (_multiLine != value)
                    {
                        _multiLine = value;
                        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("MultiLine"));
                    }
                }
            }

            #region INotifyPropertyChanged 成员

            public event PropertyChangedEventHandler PropertyChanged;

            #endregion
        }
    }
}
